package org.abc.fund.service.factorService;

import lombok.RequiredArgsConstructor;
import org.abc.fund.entity.factorEntity.FactorTree;
import org.abc.fund.entity.factorEntity.FactorTreeNode;
import org.abc.fund.repository.factorRepository.FactorTreeNodeRepository;
import org.abc.fund.repository.factorRepository.FactorTreeRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 因子树管理服务
 */
@Service
@RequiredArgsConstructor
public class FactorTreeService {

    private static final Logger log = LoggerFactory.getLogger(FactorTreeService.class);

    private final FactorTreeRepository factorTreeRepository;
    private final FactorTreeNodeRepository factorTreeNodeRepository;

    /**
     * 创建因子树
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public FactorTree createFactorTree(FactorTree factorTree) {
        // 检查树名称是否已存在
        if (factorTreeRepository.existsByTreeName(factorTree.getTreeName())) {
            throw new IllegalArgumentException("树名称已存在: " + factorTree.getTreeName());
        }

        factorTree.setCreateTime(LocalDateTime.now());
        factorTree.setUpdateTime(LocalDateTime.now());

        return factorTreeRepository.save(factorTree);
    }

    /**
     * 更新因子树
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public FactorTree updateFactorTree(Long id, FactorTree factorTree) {
        FactorTree existingTree = factorTreeRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("因子树不存在: " + id));

        // 检查树名称是否被其他树使用
        if (!existingTree.getTreeName().equals(factorTree.getTreeName()) &&
                factorTreeRepository.existsByTreeName(factorTree.getTreeName())) {
            throw new IllegalArgumentException("树名称已存在: " + factorTree.getTreeName());
        }

        existingTree.setTreeName(factorTree.getTreeName());
        existingTree.setDescription(factorTree.getDescription());
        existingTree.setBusinessScenario(factorTree.getBusinessScenario());
        existingTree.setEnabled(factorTree.getEnabled());
        existingTree.setSortOrder(factorTree.getSortOrder());
        existingTree.setUpdateTime(LocalDateTime.now());
        existingTree.setUpdatedBy(factorTree.getUpdatedBy());

        return factorTreeRepository.save(existingTree);
    }

    /**
     * 删除因子树
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public void deleteFactorTree(Long id) {
        FactorTree factorTree = factorTreeRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("因子树不存在: " + id));

        // 删除树下的所有节点
        List<FactorTreeNode> nodes = factorTreeNodeRepository.findByFactorTreeIdOrderByLevelAscSortOrderAsc(id);
        factorTreeNodeRepository.deleteAll(nodes);

        factorTreeRepository.delete(factorTree);
    }

    /**
     * 根据ID查找因子树
     */
    @Cacheable(value = "treeCache", key = "#id")
    @Transactional(readOnly = true)
    public Optional<FactorTree> findById(Long id) {
        return factorTreeRepository.findById(id);
    }

//    /**
//     * 根据树名称查找因子树
//     */
//    @Transactional(readOnly = true)
//    public Optional<FactorTree> findByTreeName(String treeName) {
//        return factorTreeRepository.findByTreeName(treeName);
//    }
//
    /**
     * 分页查询因子树
     */
    @Transactional(readOnly = true)
    public Page<FactorTree> findFactorTrees(FactorTree.BusinessScenario businessScenario, Boolean enabled, Pageable pageable) {
        if (businessScenario != null && enabled != null) {
            return factorTreeRepository.findByBusinessScenarioAndEnabled(businessScenario, enabled, pageable);
        } else {
            return factorTreeRepository.findAll(pageable);
        }
    }

    /**
     * 获取所有因子树（支持过滤）
     */
    @Transactional(readOnly = true)
    public List<FactorTree> getAllFactorTrees(FactorTree.BusinessScenario businessScenario, Boolean enabled) {
        if (businessScenario != null && enabled != null) {
            return factorTreeRepository.findByBusinessScenarioAndEnabled(businessScenario, enabled);
        } else if (businessScenario != null) {
            return factorTreeRepository.findByBusinessScenario(businessScenario);
        } else if (enabled != null) {
            return factorTreeRepository.findByEnabled(enabled);
        } else {
            return factorTreeRepository.findAll();
        }
    }

    /**
     * 根据业务场景查找因子树列表
     */
    @Cacheable(value = "treeCache", key = "'scenario_' + #businessScenario")
    @Transactional(readOnly = true)
    public List<FactorTree> findByBusinessScenario(FactorTree.BusinessScenario businessScenario) {
        return factorTreeRepository.findByBusinessScenario(businessScenario);
    }

    /**
     * 根据是否启用查找因子树列表
     */
    @Transactional(readOnly = true)
    public List<FactorTree> findByEnabled(Boolean enabled) {
        return factorTreeRepository.findByEnabled(enabled);
    }

    /**
     * 根据树名称模糊查询
     */
    @Transactional(readOnly = true)
    public List<FactorTree> findByTreeNameContaining(String treeName) {
        return factorTreeRepository.findByTreeNameContaining(treeName);
    }

    /**
     * 启用/禁用因子树
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public FactorTree toggleFactorTreeStatus(Long id, Boolean enabled) {
        FactorTree factorTree = factorTreeRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("因子树不存在: " + id));

        factorTree.setEnabled(enabled);
        factorTree.setUpdateTime(LocalDateTime.now());

        return factorTreeRepository.save(factorTree);
    }

    /**
     * 创建树节点
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public FactorTreeNode createTreeNode(FactorTreeNode treeNode) {
        // 检查节点名称在同一父节点下是否已存在
        if (treeNode.getParentId() != null &&
                factorTreeNodeRepository.existsByParentIdAndNodeName(treeNode.getParentId(), treeNode.getNodeName())) {
            throw new IllegalArgumentException("节点名称在同一父节点下已存在: " + treeNode.getNodeName());
        }

        // 设置层级和路径
        if (treeNode.getParentId() == null) {
            treeNode.setLevel(0);
            treeNode.setPath("/" + treeNode.getNodeName());
        } else {
            FactorTreeNode parentNode = factorTreeNodeRepository.findById(treeNode.getParentId())
                    .orElseThrow(() -> new IllegalArgumentException("父节点不存在: " + treeNode.getParentId()));
            treeNode.setLevel(parentNode.getLevel() + 1);
            treeNode.setPath(parentNode.getPath() + "/" + treeNode.getNodeName());
        }

        treeNode.setCreateTime(LocalDateTime.now());
        treeNode.setUpdateTime(LocalDateTime.now());

        return factorTreeNodeRepository.save(treeNode);
    }

    /**
     * 更新树节点
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public FactorTreeNode updateTreeNode(Long id, FactorTreeNode treeNode) {
        FactorTreeNode existingNode = factorTreeNodeRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("树节点不存在: " + id));

        // 检查节点名称在同一父节点下是否被其他节点使用
        if (treeNode.getParentId() != null &&
                !existingNode.getParentId().equals(treeNode.getParentId()) &&
                factorTreeNodeRepository.existsByParentIdAndNodeName(treeNode.getParentId(), treeNode.getNodeName())) {
            throw new IllegalArgumentException("节点名称在同一父节点下已存在: " + treeNode.getNodeName());
        }

        existingNode.setNodeName(treeNode.getNodeName());
        existingNode.setDescription(treeNode.getDescription());
        existingNode.setNodeType(treeNode.getNodeType());
        existingNode.setParentId(treeNode.getParentId());
        existingNode.setFactor(treeNode.getFactor());
        existingNode.setSortOrder(treeNode.getSortOrder());
        existingNode.setEnabled(treeNode.getEnabled());
        existingNode.setUpdateTime(LocalDateTime.now());
        existingNode.setUpdatedBy(treeNode.getUpdatedBy());

        // 更新层级和路径
        if (treeNode.getParentId() == null) {
            existingNode.setLevel(0);
            existingNode.setPath("/" + treeNode.getNodeName());
        } else {
            FactorTreeNode parentNode = factorTreeNodeRepository.findById(treeNode.getParentId())
                    .orElseThrow(() -> new IllegalArgumentException("父节点不存在: " + treeNode.getParentId()));
            existingNode.setLevel(parentNode.getLevel() + 1);
            existingNode.setPath(parentNode.getPath() + "/" + treeNode.getNodeName());
        }

        return factorTreeNodeRepository.save(existingNode);
    }

    /**
     * 删除树节点
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public void deleteTreeNode(Long id) {
        FactorTreeNode treeNode = factorTreeNodeRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("树节点不存在: " + id));

        // 删除子节点
        List<FactorTreeNode> children = factorTreeNodeRepository.findByParentIdOrderBySortOrderAsc(id);
        for (FactorTreeNode child : children) {
            deleteTreeNode(child.getId());
        }

        factorTreeNodeRepository.delete(treeNode);
    }

    /**
     * 根据树ID获取树形结构
     */
    @Cacheable(value = "treeCache", key = "'tree_' + #treeId")
    @Transactional(readOnly = true)
    public List<FactorTreeNode> getTreeStructure(Long treeId) {
        List<FactorTreeNode> allNodes = factorTreeNodeRepository.findByFactorTreeIdAndEnabledOrderByLevelAscSortOrderAsc(treeId, true);
        return buildTreeStructure(allNodes);
    }

    /**
     * 构建树形结构
     */
    private List<FactorTreeNode> buildTreeStructure(List<FactorTreeNode> allNodes) {
        // 创建节点映射
        Map<Long, FactorTreeNode> nodeMap = new HashMap<>();
        List<FactorTreeNode> rootNodes = new ArrayList<>();

        // 初始化节点映射
        for (FactorTreeNode node : allNodes) {
            nodeMap.put(node.getId(), node);
            node.setChildren(new ArrayList<>());
        }

        // 构建父子关系
        for (FactorTreeNode node : allNodes) {
            if (node.getParentId() == null) {
                // 根节点
                rootNodes.add(node);
            } else {
                // 子节点
                FactorTreeNode parent = nodeMap.get(node.getParentId());
                if (parent != null) {
                    parent.getChildren().add(node);
                }
            }
        }

        return rootNodes;
    }

    /**
     * 根据树ID获取根节点
     */
    @Transactional(readOnly = true)
    public List<FactorTreeNode> getRootNodes(Long treeId) {
        return factorTreeNodeRepository.findByFactorTreeIdAndParentIdIsNullOrderBySortOrderAsc(treeId);
    }

    /**
     * 根据父节点ID获取子节点
     */
    @Transactional(readOnly = true)
    public List<FactorTreeNode> getChildNodes(Long parentId) {
        return factorTreeNodeRepository.findByParentIdOrderBySortOrderAsc(parentId);
    }

    /**
     * 移动节点
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public FactorTreeNode moveNode(Long nodeId, Long newParentId) {
        FactorTreeNode node = factorTreeNodeRepository.findById(nodeId)
                .orElseThrow(() -> new IllegalArgumentException("节点不存在: " + nodeId));

        // 检查是否形成循环引用
        if (newParentId != null && wouldCreateCycle(nodeId, newParentId)) {
            throw new IllegalArgumentException("移动节点会形成循环引用");
        }

        // 更新父节点
        node.setParentId(newParentId);

        // 重新计算层级和路径
        if (newParentId == null) {
            node.setLevel(0);
            node.setPath("/" + node.getNodeName());
        } else {
            FactorTreeNode parentNode = factorTreeNodeRepository.findById(newParentId)
                    .orElseThrow(() -> new IllegalArgumentException("父节点不存在: " + newParentId));
            node.setLevel(parentNode.getLevel() + 1);
            node.setPath(parentNode.getPath() + "/" + node.getNodeName());
        }

        node.setUpdateTime(LocalDateTime.now());

        // 更新子节点的层级和路径
        updateChildrenLevelAndPath(node);

        return factorTreeNodeRepository.save(node);
    }

    /**
     * 检查是否会形成循环引用
     */
    private boolean wouldCreateCycle(Long nodeId, Long newParentId) {
        if (nodeId.equals(newParentId)) {
            return true;
        }

        Long currentParentId = newParentId;
        while (currentParentId != null) {
            FactorTreeNode parent = factorTreeNodeRepository.findById(currentParentId).orElse(null);
            if (parent == null) {
                break;
            }
            if (parent.getId().equals(nodeId)) {
                return true;
            }
            currentParentId = parent.getParentId();
        }

        return false;
    }

    /**
     * 更新子节点的层级和路径
     */
    private void updateChildrenLevelAndPath(FactorTreeNode parentNode) {
        List<FactorTreeNode> children = factorTreeNodeRepository.findByParentIdOrderBySortOrderAsc(parentNode.getId());
        for (FactorTreeNode child : children) {
            child.setLevel(parentNode.getLevel() + 1);
            child.setPath(parentNode.getPath() + "/" + child.getNodeName());
            child.setUpdateTime(LocalDateTime.now());
            factorTreeNodeRepository.save(child);

            // 递归更新子节点的子节点
            updateChildrenLevelAndPath(child);
        }
    }

    /**
     * 复制节点
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public FactorTreeNode copyNode(Long nodeId, Long targetParentId) {
        FactorTreeNode sourceNode = factorTreeNodeRepository.findById(nodeId)
                .orElseThrow(() -> new IllegalArgumentException("源节点不存在: " + nodeId));

        // 创建新节点
        FactorTreeNode newNode = new FactorTreeNode();
        newNode.setNodeName(sourceNode.getNodeName() + "_副本");
        newNode.setDescription(sourceNode.getDescription());
        newNode.setNodeType(sourceNode.getNodeType());
        newNode.setParentId(targetParentId);
        newNode.setFactor(sourceNode.getFactor());
        newNode.setSortOrder(sourceNode.getSortOrder());
        newNode.setEnabled(sourceNode.getEnabled());
        newNode.setCreatedBy(sourceNode.getCreatedBy());

        // 设置层级和路径
        if (targetParentId == null) {
            newNode.setLevel(0);
            newNode.setPath("/" + newNode.getNodeName());
        } else {
            FactorTreeNode parentNode = factorTreeNodeRepository.findById(targetParentId)
                    .orElseThrow(() -> new IllegalArgumentException("目标父节点不存在: " + targetParentId));
            newNode.setLevel(parentNode.getLevel() + 1);
            newNode.setPath(parentNode.getPath() + "/" + newNode.getNodeName());
        }

        newNode.setCreateTime(LocalDateTime.now());
        newNode.setUpdateTime(LocalDateTime.now());

        return factorTreeNodeRepository.save(newNode);
    }

    /**
     * 搜索节点
     */
    @Transactional(readOnly = true)
    public List<FactorTreeNode> searchNodes(Long treeId, String keyword) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return new ArrayList<>();
        }

        return factorTreeNodeRepository.findByFactorTreeIdAndNodeNameContainingIgnoreCaseOrderByLevelAscSortOrderAsc(
                treeId, keyword.trim());
    }

    /**
     * 获取节点路径
     */
    @Transactional(readOnly = true)
    public String getNodePath(Long nodeId) {
        FactorTreeNode node = factorTreeNodeRepository.findById(nodeId)
                .orElseThrow(() -> new IllegalArgumentException("节点不存在: " + nodeId));
        return node.getPath();
    }

    /**
     * 获取节点深度
     */
    @Transactional(readOnly = true)
    public int getNodeDepth(Long nodeId) {
        FactorTreeNode node = factorTreeNodeRepository.findById(nodeId)
                .orElseThrow(() -> new IllegalArgumentException("节点不存在: " + nodeId));
        return node.getLevel();
    }

    /**
     * 获取节点子树
     */
    @Transactional(readOnly = true)
    public List<FactorTreeNode> getSubtree(Long nodeId) {
        List<FactorTreeNode> allNodes = factorTreeNodeRepository.findByPathContaining(
                getNodePath(nodeId) + "/");
        return buildTreeStructure(allNodes);
    }

    /**
     * 批量操作节点
     */
    @CacheEvict(value = "treeCache", allEntries = true)
    public void batchUpdateNodes(List<Long> nodeIds, Map<String, Object> updates) {
        for (Long nodeId : nodeIds) {
            try {
                FactorTreeNode node = factorTreeNodeRepository.findById(nodeId)
                        .orElseThrow(() -> new IllegalArgumentException("节点不存在: " + nodeId));

                // 应用更新
                if (updates.containsKey("nodeName")) {
                    node.setNodeName((String) updates.get("nodeName"));
                }
                if (updates.containsKey("description")) {
                    node.setDescription((String) updates.get("description"));
                }
                if (updates.containsKey("enabled")) {
                    node.setEnabled((Boolean) updates.get("enabled"));
                }
                if (updates.containsKey("sortOrder")) {
                    node.setSortOrder((Integer) updates.get("sortOrder"));
                }

                node.setUpdateTime(LocalDateTime.now());
                factorTreeNodeRepository.save(node);
            } catch (Exception e) {
                log.error("批量更新节点失败: {}", nodeId, e);
            }
        }
    }

    /**
     * 检查树名称是否存在
     */
    @Transactional(readOnly = true)
    public boolean existsByTreeName(String treeName) {
        return factorTreeRepository.existsByTreeName(treeName);
    }
}